PRG 1.0 TXT

/*
	Triangle Tessellation Program
*/

//-----------------------------------------------------------------------------
// [CONFIG]

include "..\program_include.ocf"

object Program
{
	type		= e_program.DISPLACEMENT;
	layer_bits	= e_render_layer_bits.VIEW;
	
	ubo_data	= array /*UBO*/ {
		{ "inMaterial", e_program_data.MATERIAL }
	}

	textures	= array /*ProgramTexture*/ {
		{ "unDiffuseMap", e_texture.DIFFUSE },
		{ "unNormalMap",  e_texture.NORMAL },
		{ "unHeightMap",  e_texture.HEIGHT }
	}
	
	uniforms	= array /*string*/ {
		"transform", "unTransform."
	}
}


//-----------------------------------------------------------------------------
// [VERTEX]

#version 410 core
#pragma optimize(on)

#define ATTR_POSITION		0
#define ATTR_NORMAL			1
#define ATTR_TEXCOORD_0		2

layout(location = ATTR_POSITION)	in vec3 inPosition;
//layout(location = ATTR_NORMAL)		in vec3 inNormal;
layout(location = ATTR_TEXCOORD_0)	in vec2 inTexcoord;

uniform sampler2D	unHeightMap;

uniform struct TTransform {
	mat4	MVP;
} unTransform;


layout(std140)
uniform inMaterial {
	float	fShininess;
	float	fHeightScale;
	float	fDetailLevel;
	float	fMaxLevel;
	float	fQuadSize;
} unParams;


out	TVertexData {
	vec4	vPos;
	vec2	vTexcoord;
	float	fLevel;
} Output;


bool InScreen(in vec2 in_pos, in float z)
{
	const float		size = 1.7;
	float			quad = unParams.fQuadSize;
	return ( abs(in_pos.x) <= size &&
			 abs(in_pos.y) <= size ) ||
		    ( z > -quad && z < quad );
}


float Level(in vec4 in_pos)
{
	if ( InScreen( in_pos.xy/in_pos.w, in_pos.z ) )
	{
		float	d = unParams.fDetailLevel / length( in_pos ) - 2.0;
		return clamp( d, 1.0, unParams.fMaxLevel );
	}
	else
		return 0.0;
}

void main()
{
	gl_Position  		= vec4(inPosition, 1.0);
	Output.vTexcoord	= inTexcoord;
	vec4	pos			= vec4(inPosition, 1.0);
	pos.z			   += length( texture( unHeightMap, inTexcoord ).rgb ) * unParams.fHeightScale;
	pos					= unTransform.MVP * pos;
	Output.vPos			= pos;
	Output.fLevel		= Level( pos );
}


//-----------------------------------------------------------------------------
// [TESS_CONTROL]

#version 410 core
#pragma optimize(on)

#define I 	gl_InvocationID

layout(vertices = 3) out;

layout(std140)
uniform inMaterial {
	float	fShininess;
	float	fHeightScale;
	float	fDetailLevel;
	float	fMaxLevel;
	float	fQuadSize;
} unParams;


in	TVertexData {
	vec4	vPos;
	vec2	vTexcoord;
	float	fLevel;
} Input[];


out	vec2	vContTexcoord[];


bool InScreen(in vec2 in_pos, in float z)
{
	const float		size = 1.7;
	float			quad = unParams.fQuadSize;
	return ( abs(in_pos.x) <= size &&
			 abs(in_pos.y) <= size ) ||
		    ( z > -quad && z < quad );
}


float Level(in vec4 in_pos)
{
	if ( InScreen( in_pos.xy/in_pos.w, in_pos.z ) )
	{
		float	d = unParams.fDetailLevel / length( in_pos ) - 2.0;
		return clamp( d, 1.0, unParams.fMaxLevel );
	}
	else
		return 0.0;
}


float Level()
{
	vec4	p = (Input[0].vPos + Input[1].vPos + Input[2].vPos) / vec4(3.0, 3.0, 3.0, 1.0);
	float	l = Level( p );
	return max( max( Input[0].fLevel, Input[1].fLevel ), max( Input[2].fLevel, l ) );
}


void main()
{
	if ( I == 0 )
	{
		float	f_level = Level();
		gl_TessLevelInner[0] = f_level;
		f_level = f_level > 0.0 ? 1.0 : 0.0;
		gl_TessLevelOuter[0] = max( max( Input[1].fLevel, Input[2].fLevel ), f_level );
		gl_TessLevelOuter[1] = max( max( Input[0].fLevel, Input[2].fLevel ), f_level );
		gl_TessLevelOuter[2] = max( max( Input[0].fLevel, Input[1].fLevel ), f_level );
	}
	
	gl_out[I].gl_Position	= gl_in[I].gl_Position;
	vContTexcoord[I]		= Input[I].vTexcoord;
}


//-----------------------------------------------------------------------------
// [TESS_EVALUATION]

#version 410 core
#pragma optimize(on)

//layout(triangles, equal_spacing, ccw) in;
layout(triangles, fractional_even_spacing, ccw) in;
//layout(triangles, fractional_odd_spacing, ccw) in;

uniform sampler2D	unHeightMap;

uniform struct TTransform {
	mat4	MVP;
} unTransform;


layout(std140)
uniform inMaterial {
	float	fShininess;
	float	fHeightScale;
	float	fDetailLevel;
	float	fMaxLevel;
	float	fQuadSize;
} unParams;


in	vec2	vContTexcoord[];


out	TEvalData {
	vec2	vTexcoord;
} Output;


float PCF(in vec2 texcoord)
{
	/*float	res = 0.0;
	res += length( textureOffset( unHeightMap, texcoord, ivec2(-1,-1) ).rgb );
	res += length( textureOffset( unHeightMap, texcoord, ivec2(-1, 0) ).rgb );
	res += length( textureOffset( unHeightMap, texcoord, ivec2(-1, 1) ).rgb );
	res += length( textureOffset( unHeightMap, texcoord, ivec2( 0,-1) ).rgb );
	res += length( textureOffset( unHeightMap, texcoord, ivec2( 0, 0) ).rgb ) * 2.0;
	res += length( textureOffset( unHeightMap, texcoord, ivec2( 0, 1) ).rgb );
	res += length( textureOffset( unHeightMap, texcoord, ivec2( 1,-1) ).rgb );
	res += length( textureOffset( unHeightMap, texcoord, ivec2( 1, 0) ).rgb );
	res += length( textureOffset( unHeightMap, texcoord, ivec2( 1, 1) ).rgb );
	return ( res * 0.1 );*/
	return length( texture( unHeightMap, texcoord ).rgb );
}


void main()
{
	vec4	pos =		gl_TessCoord.x * gl_in[0].gl_Position + 
						gl_TessCoord.y * gl_in[1].gl_Position +
						gl_TessCoord.z * gl_in[2].gl_Position;
				 
	Output.vTexcoord =	gl_TessCoord.x * vContTexcoord[0] +
						gl_TessCoord.y * vContTexcoord[1] +
						gl_TessCoord.z * vContTexcoord[2];
	
	pos.z += PCF( Output.vTexcoord ) * unParams.fHeightScale;
	gl_Position = unTransform.MVP * pos;
}


//-----------------------------------------------------------------------------
// [FRAGMENT]

#version 410 core
#pragma optimize(on)

layout(location = 0)	out vec4	outDNNS;	// depth, normal(x,y), Shininness
layout(location = 1)	out vec4	outRGBM;	// colorRGB, MaterialID

uniform sampler2D	unDiffuseMap;
uniform sampler2D	unNormalMap;

layout(std140)
uniform inMaterial {
	float	fShininess;
	float	fHeightScale;
	float	fDetailLevel;
	float	fMaxLevel;
	float	fQuadSize;
} unParams;


in	TEvalData {
	vec2	vTexcoord;
} Input;


vec2 CalcOutputNormal(vec3 vNormal)
{
	vec2	res = ( vNormal.xy + vec2(1.0) ) * 0.5;
	res.x *= ( vNormal.z < 0.0 ? -1.0 : 1.0 );
	return res;
}


void main()
{
	vec3	normal = normalize( texture( unNormalMap, Input.vTexcoord ).rgb );
	
	outDNNS.r   = 0.0;//Input.fDepth;
	outDNNS.gb  = CalcOutputNormal( normalize( normal ) );
	outDNNS.a	= unParams.fShininess;
	outRGBM.rgb	= texture( unDiffuseMap, Input.vTexcoord ).rgb;
	outRGBM.a   = 0;
}

// [END]
